`timescale 1ns / 1ps

// Latency = 3
module dwc_datapath
#(
    parameter BIT_I     = 8,
    parameter BIT_W     = 5,
    parameter BIT_O     = 16
)
(
    input   clk,
    
    input   ce,
    input   ce_acc,
    input   ld_acc,
    
    input   [BIT_I-1 : 0]   i_data,
    input   [BIT_W-1 : 0]   i_wigt,
    output  [BIT_O-1 : 0]   o_data
);

localparam ZEROS = { BIT_O{1'b0} };
localparam BIT_M = BIT_I + BIT_W;

reg         [BIT_I-1 : 0] p_data;
reg  signed [BIT_W-1 : 0] p_wigt;
reg  signed [BIT_M-1 : 0] p_mult;

wire signed [BIT_O-1 : 0] addend;
reg  signed [BIT_O-1 : 0] acc;

assign o_data = acc;
assign addend = ld_acc ? acc : ZEROS;

always @(posedge clk)
begin
    if (ce) begin
        p_data <= i_data;
        p_wigt <= i_wigt;
        // p_mult <= $unsigned(p_data) * $signed(p_wigt);
        p_mult <= $signed({ 1'b0, p_data }) * $signed(p_wigt);
    end
    if (ce_acc) begin
        acc <= $signed(p_mult) + $signed(addend);
    end
end

endmodule
